package com.javaweb.web.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.javaweb.base.BaseDao;
import com.javaweb.base.BaseInject;
import com.javaweb.base.BaseSystemMemory;
import com.javaweb.base.po.Interfaces;
import com.javaweb.base.po.Module;
import com.javaweb.base.po.OperationLog;
import com.javaweb.constant.CommonConstant;
import com.javaweb.util.core.HttpUtil;
import com.javaweb.util.entity.Page;
import com.javaweb.web.eo.TokenData;
import com.javaweb.web.eo.operationLog.OperationLogListRequest;
import com.javaweb.web.eo.operationLog.OperationLogListResponse;
import com.javaweb.web.service.OperationLogService;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

/**
 * 操作日志模块业务层接口实现
 * 
 * @author tank2140896
 */
@Service("operationLogServiceImpl")
public class OperationLogServiceImpl extends BaseDao implements OperationLogService {

	/**
	 * 保存操作日志接口实现
	 * 
	 * @param operationLog 操作日志信息
	 */
	@Transactional
	@Override
	public void saveOperationLog(OperationLog operationLog) {
		operationLogDao.insert(operationLog);
	}

	/**
	 * 操作日志列表业务层接口实现
	 * 
	 * @param operationLogListRequest 操作日志列表请求参数
	 * @return Page 分页参数
	 */
	@Override
	public Page operationLogList(OperationLogListRequest operationLogListRequest) {
		List<Module> moduleList = moduleDao.selectAll();
		List<Interfaces> interfacesList = BaseSystemMemory.interfacesList;
		List<OperationLogListResponse> list = operationLogDao.operationLogList(operationLogListRequest);
		Long count = operationLogDao.operationLogListCount(operationLogListRequest);
		if(count!=null&&count>0){
			for(int i=0;i<list.size();i++){//第一层for循环不能break，必须完全执行每一步
				List<String> moduleNameList = new ArrayList<>();
				OperationLogListResponse eachOperationLogListResponse = list.get(i);
				loop:for(int j=0;j<moduleList.size();j++){
					if(moduleList.get(j).getApiUrl()!=null){
						String apiUrlSplit[] = moduleList.get(j).getApiUrl().split(CommonConstant.COMMA);
						for(String eachApiUrl:apiUrlSplit){
							if(eachOperationLogListResponse.getUrl().contains(eachApiUrl)){
								getModuleNameList(moduleList.get(j).getModuleId(),moduleList,moduleNameList);
								break loop;
							}
						}
					}
				}
				Collections.reverse(moduleNameList);
				if(moduleNameList.size()==0){//模块表没查到，表示请求的接口不受权限控制，所以要查sys_interfaces表
					for(int m=0;m<interfacesList.size();m++){
						if(eachOperationLogListResponse.getBaseUrl().equals(interfacesList.get(m).getUrl())){
							eachOperationLogListResponse.setOperateName(interfacesList.get(m).getName());
							break;
						}
					}
				}else{
					eachOperationLogListResponse.setOperateName(String.join(CommonConstant.BAR,moduleNameList));
				}
			}
		}
		Page page = new Page(operationLogListRequest,list,count);
		return page;
	}
	
	/**
	 * 向上递归获取模块名称
	 * 
	 * @param originModulePid 原上级模块ID
	 * @param moduleList 模块列表
	 * @param moduleNameList 模块名称列表
	 */
	private void getModuleNameList(String originModulePid,List<Module> moduleList,List<String> moduleNameList){
		for(int i=0;i<moduleList.size();i++){
			Module eachModule = moduleList.get(i);
			if((originModulePid!=null)&&(!CommonConstant.EMPTY_VALUE.equals(originModulePid))&&(eachModule.getModuleId().equals(originModulePid))){
				moduleNameList.add(eachModule.getModuleName());
				getModuleNameList(eachModule.getParentId(),moduleList,moduleNameList);
				break;
			}
		}
	}

	/**
	 * 操作日志切面保存接口实现
	 * @param httpServletRequest HttpServletRequest
	 * @param baseUrl URL通配
	 * @param joinPoint 切面点
	 */
	@Transactional
	@Override
	public void saveOperationLog(HttpServletRequest httpServletRequest,Interfaces interfaces,ProceedingJoinPoint joinPoint) {
		OperationLog operationLog = new OperationLog();
		String url = httpServletRequest.getRequestURL().toString();
		//获得请求参数（一般指controller方法里的所有参数）
		StringBuilder requestParameter = new StringBuilder();
		Object obj[] = joinPoint.getArgs();
		if(joinPoint!=null&&obj!=null) {
			for(int i=0;i<obj.length;i++) {
				if(obj[i] instanceof BindingResult || obj[i] instanceof TokenData || obj[i] instanceof HttpServletRequest || obj[i] instanceof HttpServletResponse) {
					continue;
				}
				try {
					requestParameter.append(new ObjectMapper().writeValueAsString(obj[i]));
				} catch (JsonProcessingException e) {
					//do nothing
				}
			}
		}
	    Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
        Map<String, String> headerMap = new HashMap<>();
        while (headerNames.hasMoreElements()) {
            String name = headerNames.nextElement();
            headerMap.put(name,httpServletRequest.getHeader(name));
        }
		operationLog.setId(idGenerator.idCreate());
		operationLog.setUrl(url);
		operationLog.setRequestHeader(headerMap.toString());
		operationLog.setBaseUrl(interfaces.getUrl());
		operationLog.setRequestMethod(httpServletRequest.getMethod());
		operationLog.setRequestParameter(requestParameter.toString());//joinPoint.getArgs().toString()*//*joinPoint.getSignature()
		operationLog.setRequestIpAddress(HttpUtil.getIpAddress(httpServletRequest));
		operationLog.setRequestTime(new Date());
		TokenData tokenData = BaseInject.getTokenData(BaseInject.getToken(httpServletRequest));
		if(tokenData!=null){
			operationLog.setUserId(tokenData.getUser().getUserId());
			operationLog.setLoginWay(tokenData.getLoginWay());
			operationLog.setClientType(tokenData.getClientType());
		}else{
			operationLog.setUserId(CommonConstant.ZERO_STRING_VALUE);//0表示无需登录即可访问
			operationLog.setLoginWay(1);//默认账号密码登录
			operationLog.setClientType(1);//默认页面端
		}
		saveOperationLog(operationLog);//记录操作日志
	}

}
